package ocrs.server.registeringSystem;

import com.google.appengine.api.datastore.Key;
//import com.google.appengine.api.users.User;

import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;

import java.util.Calendar;
import java.util.ArrayList;

@PersistenceCapable
public class OdinsFistSystem 
{
	// need to add persistent tags
	private ArrayList<User> userHolder;
	private ArrayList<Course> courseHolder;
	private int lastGeneratedCourseID;
	private int lastGeneratedStudentID;
	private MonthDayYear finalDayToDrop;
	private MonthDayYear finalDayToAdd;
	private MonthDayYear currentDate;
	
	@PrimaryKey
	@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
	private Key theKey;
	
	
	// TRY TO FIGURE OUT THE HOW TO MAKE THESE FIELDS STATIC, only one copy
	@Persistent
	private static final int MAX_NUMBER_OF_CREDITS_PER_SEMESTER = 20;
	
	@Persistent
	private static final int STUDENT_PERMISSION_LEVEL = 0;
	
	@Persistent
	private static final int TEACHER_PERMISSION_LEVEL = 1;
	
	@Persistent
	private static final int SCHOOL_ADMINISTRATOR_PERMISSION_LEVEL = 2;
	
	@Persistent
	private static final int IT_ADMINISTRATOR_PERMISSION_LEVEL = 3;
		
	@Persistent
	private static int MAX_NUMBER_OF_WAIT_LIST_SPOTS_FOR_A_COURSE = 10;
	
	
	
	
	public OdinsFistSystem()
	{
		courseHolder = new ArrayList<Course>();
		userHolder = new ArrayList<User>();
		lastGeneratedCourseID = 0;
		lastGeneratedStudentID = 0;
		finalDayToAdd = new MonthDayYear();
		finalDayToDrop = new MonthDayYear();
		currentDate = new MonthDayYear();
		updateCurrentDate();
	} // end of default constructor
	
	
	
	/** 
     * Name: getTheKey <br><br>
     * An accessor method that retrieves the the key for the object in the
     * Google datastore.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the key. <br>
     * @param None
     */
	public Key getTheKey()
	{
		return theKey;
	} // end of getTheKey()
	
	// need to constant call this method
	private void updateCurrentDate()
	{
		// retrieves the current time
		Calendar today = Calendar.getInstance();
		
		int month = today.get(Calendar.MONTH);
		int day = today.get(Calendar.DAY_OF_MONTH);
		int year = today.get(Calendar.YEAR);
		
		try
		{
		    currentDate.setAllThreeFields(month, day, year);
		}
		
		catch(NotValidArgumentException nvae)
		{
			; // do nothing, should not make it in this catch block
		}
	}
	
	
	public boolean checkIfTheEnteredPasswordIsValid(User theUser, String thePassword)
	{
		boolean wasThePasswordValid = false;
		
		if(theUser != null && thePassword != null)
			if(theUser.getPassword().compareTo(thePassword) == 0)
				wasThePasswordValid = true;
			
		return wasThePasswordValid;
	}
	
	
	// move to the system class because there is no access to the data
	public void calculateGPA(User calculateGPAForThisUser)  // could return double
	{
		int sum = 0;
		int totalQualityPoints = 0;        // SHOULD BE NUMBER OF CREDIT HOURS
		//char gradeEarned = ' ';
				
	    for(CoursePlusCharacter theCourse: 
	    	                     calculateGPAForThisUser.getCompletedCourses())
	    {
	    	// LDLDLDLDLDLDLDLLDLDLDLDL
	    	System.out.println("GRADE EARNED: " + theCourse.getTheChar());
	    	
	        switch(theCourse.getTheChar())
	        {
	            case 'A':
	            	sum += theCourse.getTheCourse().getNumberOfCredits();
	            	totalQualityPoints += 
	            		     4 * theCourse.getTheCourse().getNumberOfCredits();
	            	break;
	            	
	            case 'B':
	            	sum += theCourse.getTheCourse().getNumberOfCredits();
	            	totalQualityPoints += 
           		             3 * theCourse.getTheCourse().getNumberOfCredits();
	            	break;
	            	
	            case 'C':
	            	sum += theCourse.getTheCourse().getNumberOfCredits();
	            	totalQualityPoints += 
           		             2 * theCourse.getTheCourse().getNumberOfCredits();
	            	break;
	            	
	            case 'D':
	            	sum += theCourse.getTheCourse().getNumberOfCredits();
	            	totalQualityPoints += 
           		             theCourse.getTheCourse().getNumberOfCredits();
	            	break;
	            	
	            case 'F':
	            	totalQualityPoints += 
           		             4 * theCourse.getTheCourse().getNumberOfCredits();
	            	break;
	        } // end of switch statement
	    } // end of for statement
	    
	    try{
	    // on a 4.0 scale
	    double newGPA = (double)totalQualityPoints / sum;
	    
	    // LDLDLDLDLDLDLDLDLLDLDLDLDLDLDLDL
	    System.out.println(calculateGPAForThisUser.getCompletedCourses());
	    System.out.println("SUM: " + sum);
	    System.out.println("TOTAL QUALITY POINTS: " + totalQualityPoints);
	    System.out.println("NEW GPA: " + newGPA);
	    
	    calculateGPAForThisUser.setGPA(newGPA);
		}
		catch(NotValidArgumentException nvae)
		{
			// do nothing. shouldn't get here
		}
		
	}
	
	
	
	// could have a mode parameter to determine to calculate for grades
	// this is just calculating grades for undergraduates
	//private StringPlusCharacter[] generateAListOfNonRepeatedCourses()
	//{
	//	
	//}
	
	// ADMIN METHOD
	// ADDS THE USER INTO THE SYSTEM BY CampusID
	public void addUserToSystem(User addThisUser)
	{
		boolean addedUser = false;
		boolean encounteredADuplicate = false;
		//int compareToValue = 0;
		
		if(addThisUser != null)
		{
			// check if the user has a campusID yet
			// if not, then generate one
			String identification = addThisUser.getCampusID();
			
			try{
			// "" is the initial value set by the constructor
			if(identification == "")
				addThisUser.setCampusID(
						           Integer.toString(lastGeneratedStudentID++));
			}catch(NullReferenceException nre)
			{
				//nothing?
			}
			
			
			
		    for(int i = 0; i < userHolder.size() && addedUser == false
		                                && encounteredADuplicate == false; i++)
		    {
		    	int comparedToValue = userHolder.get(i).compareTo(addThisUser);
		    	
		    	// LDLDLDLDLDLDLLDD
		    	//System.out.println("COMP VALUE: " + comparedToValue);
		    	//System.out.println("I = " + i + " " + userHolder.get(i));
		    	//System.out.println("addThisUser: " + addThisUser);
		    	
		    	if(comparedToValue > 0)
		    	{
		    		//System.out.println("HELLO-A");
		    		userHolder.add(i, addThisUser);
		    		//addThisUser.setCampusID(
		    		//		        Integer.toString(lastGeneratedCourseID++));
		    		addedUser = true;
		    	}
		    	
		    	// not adding if a user with an identical campusID
		    	// with one already added
		    	else if(comparedToValue == 0)
		    	{	
		    	    encounteredADuplicate = true;
		    	    //System.out.println("HELLO-B");
		    	}
		    }
		    
		    // adding to the end if it was not added earlier
		    if(addedUser == false && encounteredADuplicate == false)
		    {
		    	//System.out.println("HELLO-C");
		    	userHolder.add(addThisUser);
		    	//addThisUser.setCampusID(
				//        Integer.toString(lastGeneratedCourseID++));
		    }
		}	
	}
	
	
	// LFLFLFLFLFLFLFLFLFLFLFLFLFLLFLFLFLFLFLF
	private int binarySearchUserHolder(User findThisUser)
	{
		int locationFound = -1;
		int left = 0;
		int right = userHolder.size();
		int middle = (left + right) / 2;
		boolean foundTheElement = false;
		
		User theUser = null;
		int comparedToValue = 0;
		
		while(left > right || foundTheElement == false)
		{
			theUser = userHolder.get(middle);
			comparedToValue = theUser.compareTo(findThisUser);
			
			// check the left half
			if(comparedToValue > 0)
			{
				right = middle - 1;
				middle = (left + right) / 2;
			}
			
			// check the right half
			else if(comparedToValue < 0)
			{
				left = middle + 1;
				middle = (left + right) / 2;
			}
			
			// found the element
			else
			{
				locationFound = middle;
				foundTheElement = true;
			}
		}
		
		return locationFound;
	}
	
	
	// ADMIN METHOD
	// ADDS THE USER INTO THE SYSTEM BY CampusID
	public void addCourseToSystem(Course addThisCourse)
	{
		boolean addedCourse = false;
		boolean encounteredADuplicate = false;
		
		if(addThisCourse != null)
		{
			// check if the course has a course ID
			// if not, then generate one
			String identification = addThisCourse.getCourseID();
			
			try{
			// "" is the initial value set by the constructor
			if(identification == "")
				addThisCourse.setCourseID(
						           Integer.toString(lastGeneratedCourseID++));
			}
			catch(NullReferenceException nre)
			{
				// display message or do nothing?
			}
			
			
		    for(int i = 0; i < courseHolder.size() && addedCourse == false
		                                && encounteredADuplicate == false; i++)
		    {
		    	int comparedToValue = courseHolder.get(i).compareTo(addThisCourse);
		    	
		    	if(comparedToValue > 0)
		    	{
		    		courseHolder.add(i, addThisCourse);
		    		addedCourse = true;
		    	}
		    	
		    	// not adding if a user with an identical courseID
		    	// with one already added
		    	else if(comparedToValue == 0)
		    	    encounteredADuplicate = true;
		    }
		    
		    // adding to the end if it was not added earlier
		    if(addedCourse == false && encounteredADuplicate == false)
		        courseHolder.add(addThisCourse);
		}	
	}
	
	// FLFLLFLFLFLFLFLFLLFLFLFLFLFLFLFLFLFL
	private int binarySearchCourseHolder(Course findThisCourse)
	{
		int locationFound = -1;
		int left = 0;
		int right = courseHolder.size();
		int middle = (left + right) / 2;
		boolean foundTheElement = false;
		
		Course theCourse = null;
		int comparedToValue = 0;
		
		while(left > right || foundTheElement == false)
		{
			theCourse = courseHolder.get(middle);
			comparedToValue = theCourse.compareTo(findThisCourse);
			
			// check the left half
			if(comparedToValue > 0)
			{
				right = middle - 1;
				middle = (left + right) / 2;
			}
			
			// check the right half
			else if(comparedToValue < 0)
			{
				left = middle + 1;
				middle = (left + right) / 2;
			}
			
			// found the element
			else
			{
				locationFound = middle;
				foundTheElement = true;
			}
		}
		
		return locationFound;
	}

	/*
	private User getThisUser(int index)
	{
		User theUser = null;
		
		if(numberOfUsers >= 0 && numberOfUsers > index)
		    theUser = userHolder[index];
		
		return theUser;
	}
	*/
	
	
	public String changePermissionLevel(User theAdmin, User changeThisUser, 
			                                            int newPermissionLevel)
	{
		
		String returnedMessage = "";
		
		try{
		if(theAdmin.getPermissionLevel() == IT_ADMINISTRATOR_PERMISSION_LEVEL)
		{	
			changeThisUser.setPermissionLevel(newPermissionLevel);
			returnedMessage += changeThisUser.getName() + " had their " +
			                   "permission changed to " + 
			                   showTypeOfUser(changeThisUser);
		}
		}
		catch(NotValidArgumentException nvae){
			returnedMessage+= nvae.getMessage();
		}
		return returnedMessage;
	}
	
	private String showTypeOfUser(User showThisUser)
	{
		String returnedString = "";
		int userType;
		
		if(showThisUser != null)
		{
			switch(userType = showThisUser.getPermissionLevel())
			{
			    // '0'
			    case STUDENT_PERMISSION_LEVEL:
			    	returnedString += "Student";
			    	break;
			    	
			    // '1'	
			    case TEACHER_PERMISSION_LEVEL:
			    	returnedString += "Teacher";
			    	break;
			    	
			    // '2'	
			    case SCHOOL_ADMINISTRATOR_PERMISSION_LEVEL:
			    	returnedString += "School Administrator";
			    	break;
			    	
			    // '3'
			    case IT_ADMINISTRATOR_PERMISSION_LEVEL:
			    	returnedString += "IT Administrator";
			    	break;
			    	
			    // could display student	
			    default:
			        returnedString += "NOT VALID";
			        break;   	
			}
		}
		
		return returnedString;
	}
	
	// IT-LEVEL METHOD
	// NEED TO RESET PERMISSIONS TO EXCEED MAX CREDS AFTER SEMESTER
	public String giveStudentPermissionToExceedMaxCredits(User theStudent)
	{
		String returnedString = "";
		
		if(theStudent == null)
			returnedString += "Could not change the student's permission " +
			                  "level because he/she does not exist!\n";
		
		else
		{	
			theStudent.setHasPermissionToExceedMaxCredits(true);
			returnedString += theStudent.getName() + " now has permission " +
			                  "to exceed " + 
			                  MAX_NUMBER_OF_CREDITS_PER_SEMESTER +
			                  " credits this semester";
		}
		
		return returnedString;
	}
	
	
	
	public String addCourseList(User theUser, ArrayList<Course> listOfCourses)
	{
		String listOfCourseMessages = "";
		
		if(theUser != null && listOfCourses != null)
			for(Course theCourse: listOfCourses)
			    listOfCourseMessages += addUserToCourse(theUser, theCourse);
		
		
		return listOfCourseMessages;
	}
	
	// might want to check the lastAddDay
	private String addUserToCourse(User theUser, Course theCourse)
	{
		String returnedString = "";
		
		if(theUser == null)
			returnedString += "Did not add the student because he/she does " +
			                  "not exist!\n";
		
		else if(theCourse == null)
			returnedString += "Did not add the course because it does " +
                              "not exist!\n";
		
		else if(theUser.getPermissionLevel() == STUDENT_PERMISSION_LEVEL)
			returnedString += addStudentToCourse(theUser, theCourse);
		
		else if(theUser.getPermissionLevel() == TEACHER_PERMISSION_LEVEL)
			returnedString += addTeacherToCourse(theUser, theCourse);
		
		else if(theUser.getPermissionLevel() == 
			                             SCHOOL_ADMINISTRATOR_PERMISSION_LEVEL)
			returnedString += "Did not add " + theUser.getName() +
			                  " because he/she is a school administrator!\n";
		
		else if(theUser.getPermissionLevel() ==
			                                 IT_ADMINISTRATOR_PERMISSION_LEVEL)
			returnedString += "Did not add " + theUser.getName() +
                              " because he/she is an IT administrator!\n";
		
		return returnedString;
	}
	
	
	
	// could add an input list to reuse method
	private int findIfAnyStudentCoursesConflict(User theStudent, 
			                                                 Course theCourse)
	{
		int indexWhereThereIsAConflict = -1;
		
		
		if(theStudent != null)
		{	
		    for(int i = 0; i < theStudent.getCurrentCoursesForStudent().size() 
		                              && indexWhereThereIsAConflict == -1; i++)		
			    if(theStudent.getCurrentCoursesForStudent().get(i)
			           .getTheCourse().getTimeHeld()
			           .doesTheTimesOverlap(theCourse.getTimeHeld()))
				    indexWhereThereIsAConflict = i;
		}
		
		return indexWhereThereIsAConflict;
	}
	
	
	private int findIfAnyTeacherCoursesConflict(User theTeacher, 
                                                    Course theCourse)
    {
        int indexWhereThereIsAConflict = -1;


        if(theTeacher != null)
        {	
            for(int i = 0; i < theTeacher.getTeachingTheseCourses().size() 
                                      && indexWhereThereIsAConflict == -1; i++)		
                if(theTeacher.getTeachingTheseCourses().get(i)
                       .getTimeHeld()
                       .doesTheTimesOverlap(theCourse.getTimeHeld()))
                    indexWhereThereIsAConflict = i;
        }

        return indexWhereThereIsAConflict;
    }

	
	
	
	
	private ArrayList<String> findListOfClassesThatDidNotMeetPrerequistes(
			                                User theUser, Course useThisCourse)
	{
		ArrayList<String> didNotTakeTheseClasses = new ArrayList<String>();
		
		for(int i = 0; i < 
		         useThisCourse.getPrerequisitesNeededForThisCourse().size(); i++)
		{
			if(theUser.getCompletedCourses()
					.contains(useThisCourse
						.getPrerequisitesNeededForThisCourse().get(i)) == false)
			{
			    didNotTakeTheseClasses.
			     add(useThisCourse.getPrerequisitesNeededForThisCourse().get(i));
			}
		}
		
		return didNotTakeTheseClasses;
		    
	}
	
	
	// COULD GENERATE A LIST AND WEED OUT SEARCH RESULTS WITH BIN SEARCH
	private boolean checkIfTheCourseWasAlreadyAdded(User theStudent, 
			                                                  Course theCourse)
	{
		boolean theCourseWasPreviouslyAdded = false;
		int compareToValue = 0;
		
		if(theStudent != null && theCourse != null)	
		    for(int i = 0; i < theStudent.getCurrentCoursesForStudent().size() 
		                          && theCourseWasPreviouslyAdded == false; i++)
		    {
			    compareToValue = 
				       theStudent.getCurrentCoursesForStudent().get(i).
				                           getTheCourse().compareTo(theCourse);
			
			    if(compareToValue == 0)
				    theCourseWasPreviouslyAdded = true;
		    }
		
		return theCourseWasPreviouslyAdded;
	}
	
	
	// admin override ability
	// add if the course was already added
	// add prerequisite checking
	// could add higher level course completed and deny
	private String addStudentToCourse(User addThisStudent, Course theCourse)
	{
		String returnedMessage = "";
		int whereDoesTheConflictOccur =
			        findIfAnyStudentCoursesConflict(addThisStudent, theCourse);
		
		boolean wasTheCourseAddedPreviously =
			        checkIfTheCourseWasAlreadyAdded(addThisStudent, theCourse);
		
		/* LDLDLDLDLDLLDLDLDLDLDLD
		System.out.println("CONDITION #1: " + (theCourse.getStudentList().size() == theCourse.getCapacity()));
		System.out.println("CONDITION #2: " + (theCourse.getWaitList().size() < 
			                       MAX_NUMBER_OF_WAIT_LIST_SPOTS_FOR_A_COURSE));
	    */
		
		/*
		if(addThisStudent != null)
		{	
		    System.out.println("ADD THIS STUDENT: " + addThisStudent.getName());
		    System.out.println("WANTED CLASS: " + theCourse.getCourseName());
		    System.out.println("Num Credits for Student: " + addThisStudent.getNumberOfCreditsForThisSemester());
		    System.out.println("")
		
		    System.out.println("COND #1: " + ((addThisStudent.getNumberOfCreditsForThisSemester() + 
	                       theCourse.getCapacity()) > MAX_NUMBER_OF_CREDITS_PER_SEMESTER));
	        System.out.println("COND #2: " + ((addThisStudent.getHasPermissionToExceedMaxCredits() == false)));
		}
		*/
		
		// LDLDLDLDLDLLDLD
		System.out.println("WHERE DOES THE CONFLICT OCCUR: " + whereDoesTheConflictOccur);
		
		
		if(addThisStudent == null)
			returnedMessage += "Did not add the student becuase he/she does " +
			                   "not exist!\n";
		
		else if(addThisStudent.getPermissionLevel() != 
			                                          STUDENT_PERMISSION_LEVEL)
			returnedMessage += "Did not add " + addThisStudent.getName() +
			                   " because this user is not a student!\n";
		
		else if((theCourse.getStudentList().size() == theCourse.getCapacity()) 
			       && (theCourse.getWaitList().size() < 
			                       MAX_NUMBER_OF_WAIT_LIST_SPOTS_FOR_A_COURSE))
	    { 
			returnedMessage += addThisStudent.getName() +
			                   " was added to the " + 
			                   theCourse.getCourseName() + "'s wait list!\n";
			
			addThisStudent.getWaitListedCourses().add(theCourse);
			theCourse.getWaitList().add(addThisStudent);
	    }
		
		else if((theCourse.getStudentList().size() == theCourse.getCapacity()) 
			       && (theCourse.getWaitList().size() == 
			                       MAX_NUMBER_OF_WAIT_LIST_SPOTS_FOR_A_COURSE))
			returnedMessage += "Did not add " + addThisStudent.getName() +
			                   " because the class is full!\n";
		
		else if((addThisStudent.showNumberOfCreditsForThisSemester() + 
			         theCourse.getNumberOfCredits()) > 
		             MAX_NUMBER_OF_CREDITS_PER_SEMESTER &&
			         addThisStudent.getHasPermissionToExceedMaxCredits() == 
			        	                                                 false)
			returnedMessage += "Did not add " + addThisStudent.getName() +
			                   " because the student does not have " +
			                   "permission to take over " +
			                   MAX_NUMBER_OF_CREDITS_PER_SEMESTER + " in " +
			                   "a semester!\n";
		
		else if(whereDoesTheConflictOccur >= 0)
			returnedMessage += "Did not add " + addThisStudent.getName() +
			                   " because the student's current courses " +
			                   "conflict with the attempted course!\n" +
			                   "[ " + addThisStudent
			                   .getCurrentCoursesForStudent()
			                   .get(whereDoesTheConflictOccur)
			                   .getTheCourse().getCourseName() + " (" +
			                   addThisStudent
			                   .getCurrentCoursesForStudent()
			                   .get(whereDoesTheConflictOccur)
			                   .getTheCourse().getTimeHeld()
			                   .showStartingToEndingTime() + ") ]\n";
		
		// there was not errors to stop the student from signing up for
		// a course
		else
		{
			addThisStudent.getCurrentCoursesForStudent()
			    .add(new CoursePlusCharacter(theCourse, ' '));
			
//			addThisStudent.setTotalNumberOfCredits(
//				addThisStudent.getNumberOfCreditsForThisSemester() +
//				theCourse.getNumberOfCredits());
			
			theCourse.getStudentList().add(addThisStudent);
			
			returnedMessage += addThisStudent.getName() + " was sucessfully " +
                               "added to " + theCourse.getCourseName() + "\n";
		}
		 
		
		return returnedMessage;
	}
	
	
	
	// add if the course was already added
	// add prerequisite checking
	// could add higher level course completed and deny
	private String addTeacherToCourse(User addThisTeacher, Course theCourse)
	{
		String returnedMessage = "";
		int whereDoesTheConflictOccur =
			        findIfAnyTeacherCoursesConflict(addThisTeacher, theCourse);
		boolean wasTheCourseAddedPreviously =
			        checkIfTheCourseWasAlreadyAdded(addThisTeacher, theCourse);
		
		// LDLDLDLDLDLLDLD
		System.out.println("WHERE DOES THE CONFLICT OCCUR: " + whereDoesTheConflictOccur);
		
		try{
		if(addThisTeacher == null)
			returnedMessage += "Did not add the teacher becuase he/she does " +
			                   "not exist!\n";
		
		else if(whereDoesTheConflictOccur >= 0)
			returnedMessage += "Did not add " + addThisTeacher.getName() +
			                   " to be the instructor because this course " +
			                   "conflicted! [" +
			                   addThisTeacher.getTeachingTheseCourses()
			                   .get(whereDoesTheConflictOccur).getCourseName() +
			                   " (" +
			                   addThisTeacher.getTeachingTheseCourses()
			                   .get(whereDoesTheConflictOccur).getTimeHeld()
			                   .showStartingToEndingTime() + ") ]\n";
		
		else
		{
			addThisTeacher.getTeachingTheseCourses().add(theCourse);
			
			theCourse.setInstructorName(addThisTeacher.getName());
			
			returnedMessage += addThisTeacher.getName() + " was sucessfully " +
                               "added to " + theCourse.getCourseName() + "\n";
		}
		}catch(NullReferenceException nre)
		{
			returnedMessage = nre.getMessage();
		}
		
		return returnedMessage;
	}
	
	
	// FLFLFLFLLFLFLFLFLFLFLFLF
	public String toString()
	{
		String returnThisString = "";
		
		for(int i = 0; i < userHolder.size(); i++)
			returnThisString += userHolder.get(i) + "\n";
		
		for(int i = 0; i < courseHolder.size(); i++)
			returnThisString += courseHolder.get(i) + "\n";
		
		return returnThisString;
	}
	
	
	/*
	public void moveCurrentCoursesToCompleted()
	{
		int i = 0;
		
		if(completedCourses.length < 
				(numberOfCurrentCoursesForStudent + numberOfCompletedCourses))
				increaseSizeOfCompletedCourses();
			
		
		while(currentCoursesForStudent[i] != null)
		{
			completedCourses[numberOfCompletedCourses++] =
				        new StringPlusCharacter(currentCoursesForStudent[i]);
			
			i++;
		}
	}
	*/
	
	// admin override ability
	public String removeCourse(User theUser, Course theCourse)
	{
		String returnedString = "";
		
		if(theUser != null && theCourse != null)
		{
			if(theUser.getPermissionLevel() == STUDENT_PERMISSION_LEVEL)
				returnedString += ""; //removeCourseFromStudent(theUser, theCourse);
				
			else if(theUser.getPermissionLevel() == TEACHER_PERMISSION_LEVEL)
				returnedString += ""; //removeCourseFromTeacher(theUser, theCourse);
			
			else if(theUser.getPermissionLevel() == 
					    SCHOOL_ADMINISTRATOR_PERMISSION_LEVEL ||
					    theUser.getPermissionLevel() ==
					    	                 IT_ADMINISTRATOR_PERMISSION_LEVEL)
				returnedString += "Did not remove " + theCourse.getCourseName() +
				                  "because the user is administrator!\n";
		}
		
		return returnedString;
	}
	
	
	// ADMIN method
	public String changeLastDayToDropDate(int month, int dayNumber, int year)
	{
		String returnedString = "";
		String isTheInputValid = "";
		
		try
		{
			isTheInputValid =
		    MonthDayYear.checkIfTheCalendarDateIsValid(month, dayNumber, year);
		
		    // the check method should return an empty string if there was no problems 
		    if(isTheInputValid.equals(""))
		    {
			    /*
		    	System.out.println("777777777777777777777777777");
			    System.out.println("MONTH: " + month);
			    System.out.println("DAY: " + dayNumber);
			    System.out.println("YEAR: " + year);
			    System.out.println(showLastDayToDrop());
			    */
			
			    finalDayToDrop.setAllThreeFields(month, dayNumber, year);
			
			    /*
			    System.out.println(showLastDayToDrop());
			    System.out.println("777777777777777777777777777");
			    */
			
			    returnedString += "The final day to DROP was changed to " + 
			                      finalDayToDrop + "\n";
		    } // end of if statement
		
		    else
			    returnedString += "The final day to DROP was NOT changed " +
			                      "because " + isTheInputValid + "\n";
		} // end of try block
		
		catch(NotValidArgumentException nvae)
		{
			returnedString += nvae.getMessage();
		}
		
		return returnedString;
	}
	
	
	// ADMIN method
	public String changeLastDayToAddDate(int month, int dayNumber, int year)
	{
		String returnedString = "";
		
		try
		{
		    String isTheInputValid = 
	        MonthDayYear.checkIfTheCalendarDateIsValid(month, dayNumber, year);
		
		    // the check method should return an empty string if there was no
		    // problems 
		    if(isTheInputValid.equals(""))
		    {
			    finalDayToAdd.setAllThreeFields(month, dayNumber, year);
			    returnedString += "The final day to ADD was changed to " + 
			                      finalDayToAdd + "\n";
		    } // end of if statement
		
		    else
			    returnedString += "The final day to ADD was NOT changed " +
			                      "because " + isTheInputValid + "\n";
		} // end of try block
		
		catch(NotValidArgumentException nvae)
		{
			returnedString += nvae.getMessage();
		}
		
		return returnedString;
	}
	
	
	
	
	//public String change
	
	
	
	
	// remove the boolean parameter
	/*
	private boolean removeCourseFromStudent(User theUser, Course theCourse) //, 
			                                    //boolean didTheWithdrawDatePass)
	{
		int locationFound = theUser.getCurrentCoursesForStudent().indexOf(theCourse);
		
		if(locationFound >= 0 && theUser.getPermissionLevel() == STUDENT_PERMISSION_LEVEL)
		{
			StringPlusCharacter[] courseList = 
				                         theUser.getCurrentCoursesForStudent();
			int numberOfCourses = theUser.getNumberOfCurrentCoursesForStudent();
			
			// setting the grade for the course to be 'W'
			if(didTheWithdrawDatePass == true)
				courseList[locationFound].setTheChar('W');
				 
			
			else
			{	
			    shiftCoursesOver(theUser, locationFound);
			    theUser.setNumberOfCurrentCoursesForStudent(
			    		                                  numberOfCourses - 1);
			}
		}
		
		else if(locationFound >= 0 
				   && theUser.getPermissionLevel() == TEACHER_PERMISSION_LEVEL)
		{
			int numberOfCourses = theUser.getNumberOfCurrentCoursesTaught();
			
			shiftCoursesOver(theUser, locationFound);
			theUser.setNumberOfCurrentCoursesTaught(numberOfCourses - 1);
		}
		
		return (locationFound >= 0);
	}
	
	
	
	// RETURN TYPE AND PARAMETER AS AN ARRAYLIST?
	// I FEEL THAT AN ARRAYLIST WILL BE HELPFUL
	// remove the boolean parameter
	public String dropCourse(User theUser, String[] listOfCourses, 
			                                        boolean passedWithdrawDate)
	{
		String listOfCoursesNotRemoved = "";
		boolean wasTheCourseRemoved = false;
		
		for(String theCourse: listOfCourses)
		{
			wasTheCourseRemoved = removeCourse(theUser, theCourse, 
					                                       passedWithdrawDate);
			
			if(wasTheCourseRemoved == false)
				listOfCoursesNotRemoved += theCourse + " ";
		}
		
		return listOfCoursesNotRemoved;
	}
	*/
	
	
	
	public String showUserInformation(User theUser)
	{
		String userInfoString = "";
		// String.format(format, args)
		// do I need to run calculateGPA method before calling this method
		// CURRENT COURSES NEEDS 18 to 20 SPACES
		
		if(theUser == null)
			userInfoString += "Can not the user's information because " +
			                  "does not exist!\n";
		
		else if(theUser.getPermissionLevel() == STUDENT_PERMISSION_LEVEL)
			userInfoString += theUser.showStudentInfo() + "\n\n";
		
		else if(theUser.getPermissionLevel() == TEACHER_PERMISSION_LEVEL)
			userInfoString += theUser.showTeacherInfo() + "\n\n";
		
		else if(theUser.getPermissionLevel() == 
			        SCHOOL_ADMINISTRATOR_PERMISSION_LEVEL ||
			            theUser.getPermissionLevel() == 
			            	                IT_ADMINISTRATOR_PERMISSION_LEVEL)
			userInfoString += theUser.showAdminInfo();
		
		return userInfoString;
	}
	
	
	
	public String showTeacherCourses(User theTeacher)
	{
		String returnedString = "";
		
		if(theTeacher.getPermissionLevel() == TEACHER_PERMISSION_LEVEL)
			returnedString += theTeacher.showCurrentCoursesTaught() + "\n";
		
		else
			returnedString += theTeacher.getName() + " is not an instructor, " +
			                  "so this user is not teaching any courses!\n";
		
		return returnedString;
	}
	
	
	public String showLastDayToDrop()
	{
		return finalDayToDrop.toString() + "\n";
	}
	
	public String showLastDayToAdd()
	{
		return finalDayToAdd.toString() + "\n";
	}
	
	//////////////////////////////////////////////////////////////////////////
	public String showCourseList()
	{
		return courseHolder.toString();
	}
	
	
	public String showUserList()
	{
		return userHolder.toString();
	}
	
	/*
	public void test()
	{
		finalDayToAdd.set(2009, 11, 1);
		finalDayToDrop.set(2010, 1, 1);
		
		System.out.println(finalDayToAdd.getTime());
		System.out.println(finalDayToDrop.getTime());
		System.out.println(finalDayToAdd.compareTo(finalDayToDrop));
		System.out.println("A".compareTo("B"));
	}
	*/
	///////////////////////////////////////////////////////////////////////////////////
	
	
	
	// drop = CHECK WAIT LIST
	public static void main(String[] args)
	{
		OdinsFistSystem ofs = new OdinsFistSystem();
		User nullUserReference = null;
        
		// creating users and setting field
		User abc = new User();
        
		try{
		abc.setName("David");
        //abc.setCampusID("00001");
        
        User def = new User();
        def.setName("Nick");
        //def.setCampusID("00002");
        
        User ghi = new User();
        ghi.setName("Jasmine");
        //ghi.setCampusID("00003");
        
        User jkl = new User();
        jkl.setName("Leandro");
        //jkl.setCampusID("00004");
        
        ofs.addUserToSystem(def);
        ofs.addUserToSystem(abc);
        ofs.addUserToSystem(jkl);
        ofs.addUserToSystem(ghi);
        ofs.addUserToSystem(abc);
		
		// creating classes for the student
		Course classA = new Course();
		classA.setCourseName("A");
		Course classB = new Course();
		classB.setCourseName("B");
		Course classC = new Course();
		classC.setCourseName("C");
		Course classD = new Course();
		classD.setCourseName("D");
		
		// adding courses
		ofs.addCourseToSystem(classB);
		ofs.addCourseToSystem(classD);
		ofs.addCourseToSystem(classC);
		ofs.addCourseToSystem(classA);
		
		
		// checking the items stored in the course list
		System.out.println(ofs);
		
		System.out.println("TESTING THE ADDING METHODS");
		System.out.println("VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV");
		
		// testing the addStudentToCourse()
		// trying to get the null message
		System.out.println(ofs.addStudentToCourse(nullUserReference, classA));
		
		
		// changing the user to be a different type of user
		abc.setPermissionLevel(3);
		
		// testing the addStudentToCourse()
		// trying to get the not student message
		System.out.println(ofs.addStudentToCourse(abc, classA));
		
		
		// changing the User back as a student
		abc.setPermissionLevel(0);
		
		// testing adding to a wait list by change the capacity of the course
		classA.setCapacity(1);
		
		System.out.println("CHECKING THE CAPACITY OF CLASS A: " + 
				                                         classA.getCapacity());
		
		// def should be added to the wait list
		System.out.println(ofs.addStudentToCourse(abc, classA));
		System.out.println(ofs.addStudentToCourse(def, classA));
		
		// printing the system's state
		System.out.println(ofs);
		
		// adding another student to classA, it should result in a
		// can not add student name because the class is full
		// WORKS WHEN THE NUMBER OF WAIT LIST SPOTS WAS CHANGED TO ONE
		//System.out.println(ofs.addStudentToCourse(ghi, classA));
		
		// trying to get the max number of credits message
		//abc.setNumberOfCreditsForThisSemester(19);
	
		classD.setCapacity(5);
		classD.setNumberOfCredits(3);
		System.out.println(ofs.addStudentToCourse(abc, classD));
		
		// trying to get the conflict time message
		classC.setCapacity(5);
		
//		System.out.println("NUMBER OF CREDS FOR DAVID: " + 
//				                      abc.getNumberOfCreditsForThisSemester());
//		System.out.println("NUMBER OF CREDS FOR CLASS C: " + 
//				                                  classC.getNumberOfCredits());
//		System.out.println(ofs.addStudentToCourse(abc, classC));
		
		
		/*
		// print out the list of courses and testing the binary search (WORKS)
		System.out.println("########################################################");
		System.out.println(ofs.showCourseList());
		System.out.println("Location of classA: " + ofs.binarySearchCourseHolder(classA));
		System.out.println("Location of classB: " + ofs.binarySearchCourseHolder(classB));
		System.out.println("Location of classC: " + ofs.binarySearchCourseHolder(classC));
		System.out.println("Location of classD: " + ofs.binarySearchCourseHolder(classD));
		
		// print out the list of students and testing the binary search (WORKS)
		System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
		System.out.println(ofs.showUserList());
		System.out.println("Location of David: " + ofs.binarySearchUserHolder(abc));
		System.out.println("Location of Nick: " + ofs.binarySearchUserHolder(def));
		System.out.println("Location of Jasmine: " + ofs.binarySearchUserHolder(ghi));
		System.out.println("Location of Leandro: " + ofs.binarySearchUserHolder(jkl));
		*/
		
		
		// Testing calculateGPA method (WORKS)
		ArrayList<CoursePlusCharacter> cpc = new ArrayList<CoursePlusCharacter>();
		classA.setNumberOfCredits(4);
		classB.setNumberOfCredits(3);
		cpc.add(new CoursePlusCharacter(classA, 'A'));
		cpc.add(new CoursePlusCharacter(classB, 'B'));
		abc.setCompletedCourses(cpc);
		ofs.calculateGPA(abc);
		System.out.println(abc.getGPA());
		
		
		System.out.println("*******************************************************");
		// Testing teacher methods
		User teacherA = new User();
		User teacherB = new User();
		User teacherC = new User();
		User teacherD = new User();
		
		
		// changing the users to become teachers
		teacherA.setPermissionLevel(TEACHER_PERMISSION_LEVEL);
		teacherB.setPermissionLevel(TEACHER_PERMISSION_LEVEL);
		teacherC.setPermissionLevel(TEACHER_PERMISSION_LEVEL);
		teacherD.setPermissionLevel(TEACHER_PERMISSION_LEVEL);
		
		// adding names to the teacher
		teacherA.setName("PROF A");
		teacherB.setName("PROF B");
		teacherC.setName("PROF C");
		teacherD.setName("PROF D");
		
		teacherA.setPassword("Jelly JAM");
		
		// trying the new addUserToCourseMethod
		System.out.println(ofs.addUserToCourse(teacherA, classA));
		// should be denied
		System.out.println(ofs.addUserToCourse(teacherA, classB));
		
		System.out.println(ofs.showCourseList());
		
		// testing password check method
		// should return false
		System.out.println(ofs.checkIfTheEnteredPasswordIsValid(teacherA, "Jelly Jam"));
		// should return true
		System.out.println(ofs.checkIfTheEnteredPasswordIsValid(teacherA, "Jelly JAM"));
		// adding another course to teacherA
		//classB.setTimeHeld(new Time(1000, 1200, false));
		// print out the instructor's courses
		
		
		// testing the changeLastdayTo.... methods
		// month = 0 -> January
		System.out.println(ofs.changeLastDayToDropDate(1, 29, 2010));
		System.out.println(ofs.showLastDayToDrop());
		}
		catch(NotValidArgumentException nvae)
		{
			//nothing?
		}
		catch(NullReferenceException nre)
		{
			//nothing
		}	
		}	
}